package com.ruoyi.web.controller.system;

import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.Application;
import com.ruoyi.system.domain.StudentInfo;
import com.ruoyi.system.domain.TeacherInfo;
import com.ruoyi.system.service.IApplicationService;
import com.ruoyi.system.service.IStudentInfoService;
import com.ruoyi.system.service.ITeacherInfoService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 志愿申请Controller
 *
 * @author ltr
 * @date 2024-10-23
 */
@RestController
@RequestMapping("/system/application")
public class ApplicationController extends BaseController
{
    @Autowired
    private IApplicationService applicationService;

    @Autowired
    private IStudentInfoService studentInfoService;

    @Autowired
    private ITeacherInfoService teacherInfoService;

    // ==================== 学生端接口 ====================

    /**
     * 查询当前学生的志愿申请列表（学生端）
     */
    @PreAuthorize("@ss.hasRole('student')")
    @GetMapping("/my/list")
    public AjaxResult myList()
    {
        Long studentId = getCurrentStudentId();
        if (studentId == null)
        {
            return error("请先完善学生信息");
        }

        List<Application> list = applicationService.selectApplicationListByStudentId(studentId);
        return success(list);
    }

    /**
     * 学生申请志愿（学生端）
     */
    @PreAuthorize("@ss.hasRole('student')")
    @Log(title = "志愿申请", businessType = BusinessType.INSERT)
    @PostMapping("/apply")
    public AjaxResult apply(@RequestBody Application application)
    {
        Long studentId = getCurrentStudentId();
        if (studentId == null)
        {
            return error("请先完善学生信息");
        }

        // 设置学生ID和创建人
        application.setStudentId(studentId);
        application.setCreateBy(getUsername());

        return toAjax(applicationService.applyForTopic(application));
    }

    /**
     * 学生取消志愿申请（学生端）
     */
    @PreAuthorize("@ss.hasRole('student')")
    @Log(title = "取消志愿", businessType = BusinessType.UPDATE)
    @PutMapping("/cancel/{applicationId}")
    public AjaxResult cancel(@PathVariable Long applicationId)
    {
        Long studentId = getCurrentStudentId();
        if (studentId == null)
        {
            return error("请先完善学生信息");
        }

        return toAjax(applicationService.cancelApplication(applicationId, studentId));
    }

    /**
     * 检查学生是否可以申请指定优先级的志愿（学生端）
     */
    @PreAuthorize("@ss.hasRole('student')")
    @GetMapping("/check/canApply/{priority}")
    public AjaxResult checkCanApply(@PathVariable Integer priority)
    {
        Long studentId = getCurrentStudentId();
        if (studentId == null)
        {
            return error("请先完善学生信息");
        }

        boolean canApply = applicationService.canStudentApply(studentId, priority);
        return success(canApply);
    }

    /**
     * 查询学生的志愿统计信息（学生端）
     */
    @PreAuthorize("@ss.hasRole('student')")
    @GetMapping("/my/stats")
    public AjaxResult myStats()
    {
        Long studentId = getCurrentStudentId();
        if (studentId == null)
        {
            return success(0);
        }

        List<Application> list = applicationService.selectApplicationListByStudentId(studentId);
        return success(list.size());
    }

    // ==================== 教师端接口 ====================

    /**
     * 查询当前教师的题目申请列表（教师端）
     */
    @PreAuthorize("@ss.hasRole('teacher')")
    @GetMapping("/teacher/list")
    public TableDataInfo teacherList(Application application)
    {
        Long teacherId = getCurrentTeacherId();
        if (teacherId == null)
        {
            return getDataTable(null);
        }

        startPage();
        List<Application> list = applicationService.selectApplicationListByTeacherId(teacherId);
        return getDataTable(list);
    }

    /**
     * 查询指定题目的申请列表（教师端）
     */
    @PreAuthorize("@ss.hasRole('teacher')")
    @GetMapping("/teacher/topic/{topicId}")
    public AjaxResult listByTopic(@PathVariable Long topicId)
    {
        List<Application> list = applicationService.selectApplicationListByTopicId(topicId);
        return success(list);
    }

    /**
     * 查询申请详情（教师端）
     */
    @PreAuthorize("@ss.hasRole('teacher')")
    @GetMapping("/teacher/detail/{applicationId}")
    public AjaxResult getDetail(@PathVariable Long applicationId)
    {
        Long teacherId = getCurrentTeacherId();
        if (teacherId == null)
        {
            return error("请先完善教师信息");
        }

        // 检查申请是否属于该教师的题目
        if (!applicationService.checkApplicationBelongsToTeacher(applicationId, teacherId))
        {
            return error("无权查看该申请");
        }

        Application application = applicationService.selectApplicationByApplicationId(applicationId);
        return success(application);
    }

    /**
     * 教师录取学生（教师端）
     */
    @PreAuthorize("@ss.hasRole('teacher')")
    @Log(title = "录取学生", businessType = BusinessType.UPDATE)
    @PutMapping("/teacher/accept/{applicationId}")
    public AjaxResult acceptStudent(@PathVariable Long applicationId)
    {
        Long teacherId = getCurrentTeacherId();
        if (teacherId == null)
        {
            return error("请先完善教师信息");
        }

        return toAjax(applicationService.acceptStudent(applicationId, teacherId, getUsername()));
    }

    /**
     * 教师拒绝学生（教师端）
     */
    @PreAuthorize("@ss.hasRole('teacher')")
    @Log(title = "拒绝学生", businessType = BusinessType.UPDATE)
    @PutMapping("/teacher/reject/{applicationId}")
    public AjaxResult rejectStudent(@PathVariable Long applicationId, @RequestBody Application application)
    {
        Long teacherId = getCurrentTeacherId();
        if (teacherId == null)
        {
            return error("请先完善教师信息");
        }

        if (application.getReviewReason() == null || application.getReviewReason().trim().isEmpty())
        {
            return error("请填写拒绝理由");
        }

        return toAjax(applicationService.rejectStudent(applicationId, teacherId,
                application.getReviewReason(), getUsername()));
    }

    /**
     * 查询当前教师已录取的学生名单（教师端）
     */
    @PreAuthorize("@ss.hasRole('teacher')")
    @GetMapping("/teacher/accepted")
    public TableDataInfo acceptedStudents()
    {
        Long teacherId = getCurrentTeacherId();
        if (teacherId == null)
        {
            return getDataTable(null);
        }

        startPage();
        List<Application> list = applicationService.selectAcceptedStudentsByTeacherId(teacherId);
        return getDataTable(list);
    }

    /**
     * 导出已录取学生名单（教师端）
     */
    @PreAuthorize("@ss.hasRole('teacher')")
    @Log(title = "导出学生名单", businessType = BusinessType.EXPORT)
    @PostMapping("/teacher/export")
    public void export(HttpServletResponse response)
    {
        Long teacherId = getCurrentTeacherId();
        if (teacherId == null)
        {
            return;
        }

        List<Application> list = applicationService.selectAcceptedStudentsByTeacherId(teacherId);
        ExcelUtil<Application> util = new ExcelUtil<Application>(Application.class);
        util.exportExcel(response, list, "已录取学生名单");
    }

    // ==================== 管理员端接口 ====================

    /**
     * 查询所有志愿申请列表（管理员端）
     */
    @PreAuthorize("@ss.hasRole('admin') or @ss.hasRole('administrator')")
    @GetMapping("/list")
    public TableDataInfo list(Application application)
    {
        startPage();
        List<Application> list = applicationService.selectApplicationList(application);
        return getDataTable(list);
    }

    /**
     * 获取志愿申请详细信息（管理员端）
     */
    @PreAuthorize("@ss.hasRole('admin') or @ss.hasRole('administrator')")
    @GetMapping(value = "/{applicationId}")
    public AjaxResult getInfo(@PathVariable("applicationId") Long applicationId)
    {
        return success(applicationService.selectApplicationByApplicationId(applicationId));
    }

    /**
     * 删除志愿申请（管理员端）
     */
    @PreAuthorize("@ss.hasRole('admin') or @ss.hasRole('administrator')")
    @Log(title = "志愿申请", businessType = BusinessType.DELETE)
    @DeleteMapping("/{applicationIds}")
    public AjaxResult remove(@PathVariable Long[] applicationIds)
    {
        return toAjax(applicationService.deleteApplicationByApplicationIds(applicationIds));
    }

    /**
     * 导出志愿申请列表（管理员端）
     */
    @PreAuthorize("@ss.hasRole('admin') or @ss.hasRole('administrator')")
    @Log(title = "志愿申请", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void exportAdmin(HttpServletResponse response, Application application)
    {
        List<Application> list = applicationService.selectApplicationList(application);
        ExcelUtil<Application> util = new ExcelUtil<Application>(Application.class);
        util.exportExcel(response, list, "志愿申请数据");
    }

    // ==================== 工具方法 ====================

    /**
     * 获取当前登录用户的学生ID
     */
    private Long getCurrentStudentId()
    {
        Long userId = getUserId();
        StudentInfo studentInfo = studentInfoService.selectStudentInfoByUserId(userId);
        return studentInfo != null ? studentInfo.getStudentId() : null;
    }

    /**
     * 获取当前登录用户的教师ID
     */
    private Long getCurrentTeacherId()
    {
        Long userId = getUserId();
        TeacherInfo teacherInfo = teacherInfoService.selectTeacherInfoByUserId(userId);
        return teacherInfo != null ? teacherInfo.getTeacherId() : null;
    }
}